<template>
  <Siri
    v-if="state.siri"
    :text="asrText"
  />
  <div class="main-bar">
    <div
      v-for="x in 4"
      :key="x"
      class="icons absolute z-1 transform w-12px h-12px"
      :class="[x < 3 ? '-top-2px' : '-bottom-2px', [1, 4].includes(x) ? '-left-2px' : '-right-2px']"
      :style="`--tw-rotate: ${90 * (x - 1)}deg`"
    >
    </div>
    <div class="main-content text-white flex items-center h-full w-full justify-center">
      <template v-if="asrType === 'text'">
        <div
          v-if="!state.focus"
          class="enter-tips h-full w-full relatives flc"
          @click="handStart"
        >输入您想问的问题
        </div>
        <input
          v-else
          ref="asrInput"
          v-model="resultText"
          type="text"
          class="w-full h-full text-center outline-none bg-transparent px-18px"
          @blur="handEnd"
          @keydown.enter="onChart"
        />
      </template>
      <template v-else>
        <div
          v-if="!state.speak"
          class="speak text-white"
          @click="handStart"
        >点击说话</div>
        <div
          v-else
          class="finish-speek w-full h-full relative flc select-none"
          @click="handEnd"
        >
          <span class="relative z-1">{{ getTime }} 点击完成说话</span>
          <div
            class="h-full absolute z-0 top-0 left-0 bg-cyan-300/30"
            :style="{ width: `${timeValue / 20 * 100}%` }"
          >
          </div>
        </div>
      </template>
    </div>
  </div>
</template>

<script
  lang="ts"
  setup
  name="RecordAsr"
>
import { useTost } from '@/utils/comps'
import { useTtsaStore } from '@/store/ttsa'
import { PROCESS_TYPES, MODE } from '@/constants/ttsa'
import XmovASR from 'xmov-asr-sdk';

const ttsa = useTtsaStore();
const partial = ref('');
const resultText = ref('');
const asrInput = ref(null);
const asrType: any = inject('asrType')
const audioId = ref('')

const state = reactive({
  focus: false,
  speak: false,
  siri: false
});

watch(asrType, () => {
  state.speak = false;
  state.siri = false;
  if (asrService) asrService.stop()
})


const default_config = {
  origin: import.meta.env.XMOV_APP_XASR_ORIGIN,
  app_id: import.meta.env.XMOV_APP_XASR_APPID,
  secret_key: import.meta.env.XMOV_APP_XASR_SECRET_KEY,
  hotword_list: [],
};

const asrClient = (config) => {
  const asr = new XmovASR({
    origin: config.origin,
    app_id: config.app_id,
    secret_key: config.secret_key,
    hotword_list: config.hotword_list
  })
  return asr
}

const asrText = computed(() => resultText.value + partial.value);
let asrService = null;
const initAsrService = () => {
  asrService = asrClient(default_config);
  asrService.onSocketOpen = () => {
    console.log('连接已建立');
  }
  asrService.onRecStart = (res) => {
    console.log('开始识别', res);
  }
  asrService.onSentenceChange = (res) => {
    console.log('当前这句话部分结果', res);
    partial.value = res?.sentence;
    asrCheck();
  }
  asrService.onSentenceEnd = (res) => {
    resultText.value += res?.sentence;
    partial.value = '';
    console.log('一句话识别完毕', res, resultText.value);
    if (res.session_id) audioId.value = res.session_id

    asrCheck();
  }
  asrService.onRecComplete = (res) => {
    console.log('识别结束', res);
  }
  asrService.onError = (err) => {
    console.log('识别出错', err);
    useTost(err?.message);
  }
}

const start = () => {
  state.siri = true
  asrService.start()
    .then(() => {
      resultText.value = '';
      partial.value = '';
      audioId.value = '';
    })
    .catch((error) => {
      console.log('服务异常信息', error);
    });
};

const onChart = async () => {
  if (asrType.value === 'text') {
    state.focus = false;
  }
  await ttsa.chat(asrText.value, {
    asr_sessionid: audioId.value
  });
  resultText.value = '';
  audioId.value = '';
}

const stop = () => {
  state.speak = false;
  state.siri = false;
  asrService.stop();
  if (asrText.value) {
    onChart();
  }
};

const asrCheck = () => {
  if (asrText.value.length > 60) {
    stop();
  };
};

const handEnd = () => {
  if (asrType.value === 'text') {
    // input隐藏
    resultText.value = ''
    state.focus = false;
  } else {
    stop();
  }
}

// 进度动画
const timeValue = ref(0)
let loopTimer = null

const setLoop = () => {
  removeLoop()
  timeValue.value = 0
  loopTimer = setInterval(() => {
    timeValue.value++
    if (timeValue.value >= 20) {
      removeLoop()
      handEnd()
    }
  }, 1000)
}

const removeLoop = () => {
  if (loopTimer) {
    clearInterval(loopTimer)
    loopTimer = null
  }
}

const getTime = computed(() => {
  const t = timeValue.value
  const m = Math.trunc(t / 20), s = t % 20
  return `${m}:${s >= 10 ? s : '0' + s}`
})

const handStart = async () => {
  if (ttsa.mode !== MODE.QA) return
  if (asrType.value === 'text') {
    // input显示并聚焦
    state.focus = true
    nextTick(() => {
      asrInput.value.focus()
    })
  } else {
    if (ttsa.voiceLoading) {
      await ttsa.pause()
    }
    state.speak = true
    start();
    setLoop();
  }
};

onBeforeMount(() => {
  initAsrService();
});

onBeforeUnmount(() => {
  if (asrService.state !== 'unready') {
    stop();
    asrService.destroy();
  }
});
</script>

<style
  scoped 
  lang="scss"
>
@keyframes blink {
  0% {
    background-color: white;
  }

  50% {
    background-color: transparent;
  }

  100% {
    background-color: white;
  }
}

.main-bar {
  @apply relative cursor-pointer;
  width: 487px;
  height: 44px;
  background: linear-gradient(180deg, rgba(12, 46, 131, 0.5) -24.41%, rgba(20, 69, 132, 0.5) 72.59%);
  border: 1.35px solid;
  border-image-source: linear-gradient(180deg, #57A4FF 0%, rgba(53, 130, 202, 0.4) 100%);
  border-image-slice: 1;

  .icons {
    background: url('@/assets/icons/pc/bar_left_top.svg');
  }

  &::after {
    @apply absolute;
    content: '';
    width: 475px;
    left: 5px;
    top: -13px;
    height: 11.7px;
    opacity: 0.5;
    transform: perspective(100px) rotateX(30deg);
    background: linear-gradient(180deg, rgba(47, 106, 198, 0.06) -12%, #306CCA 100%);
  }

  &::before {
    @apply absolute;
    content: '';
    left: 4px;
    bottom: -1px;
    width: 474px;
    height: 11.7px;
    opacity: 0.5;
    transform: perspective(100px) rotateX(30deg);
    background: linear-gradient(180deg, rgba(47, 106, 198, 0.06) -12%, #306CCA 100%);
  }

  .main-content {
    .enter-tips {
      &::before {
        @apply absolute w-1px h-18px bg-white;
        top: calc(50% - 8px);
        left: 168px;
        content: '';
        animation: blink 1s infinite steps(1, start);
      }
    }
  }
}
</style>
